package com.turing.post.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * java身份证号码校验 身份证验证的方法，包括出生日期校验，不包括行政区划校验
 * 
 * @author zxp
 * @Jan 7, 2013
 */
public class IDCardCheck {

	// wi=2(n-1)(mod 11)
	final int[] wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 };

	// verify digit
	final int[] vi = { 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 };

	private int[] ai = new int[18];

	public IDCardCheck() {

	}

	/**
	 *  身份证校验
	 * @param idcard 身份证号
	 * @return	身份证是否正确
	 */
	public boolean Verify(String idcard) {
		if (idcard.length() == 15) {
			idcard = uptoeighteen(idcard);
		}
		if (idcard.length() != 18) {
			return false;
		}
		// System.out.println(idcard);
		// System.out.println(verifyDate(idcard));
		if (!verifyDate(idcard)) {
			return false;
		}
		String verify = idcard.substring(17, 18);
		if (verify.equals(getVerify(idcard))) {
			return true;
		}
		return false;
	}

	/**
	 * 获得身份证最后一位校验位
	 * @param eightcardid
	 * @return
	 */
	public String getVerify(String eightcardid) {
		int remaining = 0;
		if (eightcardid.length() == 18) {
			eightcardid = eightcardid.substring(0, 17);
		}
		if (eightcardid.length() == 17) {
			int sum = 0;
			for (int i = 0; i < 17; i++) {
				String k = eightcardid.substring(i, i + 1);
				ai[i] = Integer.parseInt(k);
			}
			for (int i = 0; i < 17; i++) {
				sum = sum + wi[i] * ai[i];
			}
			remaining = sum % 11;
		}
		return remaining == 2 ? "X" : String.valueOf(vi[remaining]);
	}

	/**
	 * 
	 * 描述: 15位身份证到升级到18位的算法 param fifteencardid return
	 */
	public String uptoeighteen(String fifteencardid) {
		String eighteencardid = fifteencardid.substring(0, 6);
		eighteencardid = eighteencardid + "19";
		eighteencardid = eighteencardid + fifteencardid.substring(6, 15);
		eighteencardid = eighteencardid + getVerify(eighteencardid);
		// System.out.println(eighteencardid);
		return eighteencardid;
	}

	/**
	 * 
	 * 描述:验证18位身份证中的日期是否合法,接受日期格式：2012-02-21 param eighteencardid return
	 */
	public boolean verifyDate(String eighteencardid) {
		String date = eighteencardid.substring(6, 10);
		date += "-";
		date += eighteencardid.substring(10, 12);
		date += "-";
		date += eighteencardid.substring(12, 14);
		// System.out.println(date);
		// 判断年月日的正则表达式，接受输入格式为2010-12-24，可接受平年闰年的日期
		String v = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)";
		Pattern p = Pattern.compile(v);
		Matcher m = p.matcher(date);
		return m.matches();
	}

	/**
	 * 
	 * 描述: 身份证15to18的完整算法 param sfzh return
	 */
	public String get15To18(String sfzh) {
		if (sfzh == null || sfzh.length() != 15) {
			return sfzh;
		}
		// 校验码
		char[] sVC = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' };
		// 加权因子
		int[] sEQ = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 };
		String strTemp;
		int intTemp = 0;
		strTemp = sfzh.substring(0, 6) + "19" + sfzh.substring(6);
		try {
			for (int i = 0; i < strTemp.length(); i++) {
				intTemp += Integer.parseInt(strTemp.substring(i, i + 1))
						* sEQ[i];
			}
		} catch (Exception e) {
			return sfzh;
		}
		intTemp = intTemp % 11;
		return strTemp + sVC[intTemp];
	}

	// 测试代码
	public static void main(String[] args) {
		IDCardCheck id = new IDCardCheck();
		 System.out.println(id.Verify("52020019730904789X"));
		 System.out.println(id.Verify("410182198707166016"));
		 System.out.println(new IDCardCheck().get15To18("410621198505100"));
		 System.out.println(id.verifyDate("410621198505100013"));
	}
}
